<template>
  <div>
    <h1>商户管理</h1>
    <div style="margin-top: 20px; background: #fff;border-radius: 3px;">
      <div id="menu" v-if="menuVisible" @mouseleave="menuVisible=!menuVisible">
        <div class="box-card">
          <el-button class="ring_button"
                     @click="()=>{hideContextmenu();showEdit()}" icon="el-icon-edit">修改名称
          </el-button>
          <el-button class="ring_button" v-if="nodeData.data.id==='10000'||nodeData.level===2"
                     @click="()=>{hideContextmenu();addDir()}" icon="el-icon-plus">添加文件夹
          </el-button>
          <el-button class="ring_button" v-if="nodeData.level===2"
                     @click="()=>{hideContextmenu();addShopUser()}" icon="el-icon-plus">添加商户
          </el-button>
          <el-button class="ring_button" type="danger" @click="deleteNode" v-show="nodeData.data.id !=='10001'"
                     v-if="nodeData.level===2" icon="el-icon-delete">删除
          </el-button>
        </div>
      </div>
      <el-container :style="`height:${clientHeight}px`">
        <el-aside width="300px">
          <div style="margin: 20px 20px;">
            <el-input
                placeholder="输入关键字进行过滤"
                v-model="filterText"
                prefix-icon="el-icon-search" style="color: #646C9A;"
            >
            </el-input>
            <el-tree ref="tree" :data="treeData" node-key="id" default-expand-all
                     style="margin-top: 20px;font-size: 12px;color: #646C9A;"
                     :filter-node-method="filterNode" highlight-current
                     @node-click="(data,node)=>{clickNode(data,node)}"
                     :load="loadNode" lazy @node-contextmenu="rightClick">
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <el-input :ref="`note${data.id}`" type="text" v-show="data.edit" placeholder="请输入名称"
                        v-model="data.label" @blur="saveDir(data,node)"></el-input>
              <span v-show="!data.edit"
                    :style="`${data.type==='user'&&node.parent.data.id!=='20000'?'color:blue;':''}
                    ${node.data.id==='20000'?'color:red;':''}`">
                <i class="el-icon-user-solid" v-if="node.level===3"></i>
                {{ `${!!data.shopName ? data.shopName : node.label}` }}
                <span style="margin-left: 10px">{{
                    data.type === 'dir' && node.level === 2 ? `(${node.childNodes.length})` : ''
                  }}</span>
              </span>
            </span>
            </el-tree>
          </div>
        </el-aside>
        <el-main>
          <div style="float: left;height:40px">{{ currentUser.shopName }}</div>
          <div v-show="currentUser.id">
            <div style="text-align: left">{{ currentUser.packageName }}</div>
            <div class="template-form">
              <el-form :model="currentUser" ref="currentUser" label-width="100px"
                       class="template-form__list" :rules="rules">
                <el-row :gutter="10">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="商户姓名：" prop="shopName">
                      <el-input :disabled="!editAble" v-model="currentUser.shopName" placeholder="请输入商户姓名"
                                @input="shopNameInput"></el-input>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="22">
                    <el-form-item label="上传身份证照片：" prop="idCardZmPath">
                      <el-upload :disabled="!editAble" :action="uploadUrl" list-type="picture-card" :auto-upload="true"
                                 style="display: inline-block; float: left;" ref="upload3"
                                 :headers="{'token':localStorage.getItem('token')}" :on-remove="handleRemoveZm"
                                 :on-preview="handlePictureCardPreview" :file-list="idCardZmList"
                                 :on-success="upload1Success" accept=".jpeg,.jpg,.gif,.png">
                        <i slot="default" class="el-icon-plus"></i>
                      </el-upload>
                      <el-upload :disabled="!editAble" :action="uploadUrl" list-type="picture-card" :auto-upload="true"
                                 style="display: inline-block; float: left; margin-left: 40px;" ref="upload4"
                                 :on-preview="handlePictureCardPreview" :file-list="idCardFmList"
                                 :headers="{'token':localStorage.getItem('token')}" :on-remove="handleRemoveFm"
                                 :on-success="upload2Success" accept=".jpeg,.jpg,.gif,.png">
                        <i slot="default" class="el-icon-plus"></i>
                      </el-upload>
                      <el-dialog :visible.sync="dialogVisible">
                        <img width="100%" :src="dialogImageUrl" alt="">
                      </el-dialog>
                    </el-form-item>
                  </el-col>
                  <el-col :span="22" style="margin-top: -10px">
                    <el-form-item>
                      <div><i class="el-icon-info"></i>上传图片格式为：jpg、jpeg、png</div>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="经纪人姓名：" prop="userName">
                      <el-input :disabled="!editAble" v-model="currentUser.userName" placeholder="请输入经纪人姓名"></el-input>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="门店住址：" prop="address">
                      <el-input :disabled="!editAble" v-model="currentUser.address" placeholder="请输入门店住址"></el-input>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="电话：" prop="phoneNo">
                      <el-input :disabled="!editAble" v-model="currentUser.phoneNo" placeholder="请输入电话"></el-input>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="22" style="width: 100%">
                    <el-form-item label="上传营业执照：" prop="licensePath">
                      <el-upload :disabled="!editAble" :action="uploadUrl" list-type="picture-card" :auto-upload="true"
                                 style=" display: inline-block; float: left;" ref="upload5"
                                 :headers="{'token':localStorage.getItem('token')}"
                                 :on-preview="handlePictureCardPreview" :file-list="licensePathList"
                                 accept=".jpeg,.jpg,.gif,.png" :on-remove="handleRemoveLicense"
                                 :on-success="uploadLicensePathSuccess">
                        <i slot="default" class="el-icon-plus"></i>
                      </el-upload>
                    </el-form-item>
                  </el-col>
                  <el-col :span="22" style="margin-top: -15px">
                    <el-form-item>
                      <div><i class="el-icon-info"></i>上传图片格式为：jpg、jpeg、png</div>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="登录账号：" prop="loginId">
                      <el-input :disabled="!editAble || !!oriCurrentUser.loginId" v-model="currentUser.loginId"
                                placeholder="请输入登录账号"></el-input>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10" v-if="editAble">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item label="密码：" prop="password">
                      <el-input v-model="currentUser.password" disabled type="password"
                                style="width: 70%;float:left"></el-input>
                      <el-button type="primary" @click="restPassword">恢复初始密码</el-button>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="10" v-if="editAble">
                  <el-col :span="12" style="width: 100%">
                    <el-form-item>
                      <el-tag style="width: 70%;float: left">初始密码为{{ defaultPass }}</el-tag>
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-form>
              <div class="dialog-footer">
                <span slot="footer"
                      v-if="currentUser.deleteFlag !=='1'&&userInfo.isSuperAdmin==='1'">
                  <el-button v-if="!editAble" type="danger" @click="deleteUser">停用</el-button>
                  <el-button v-if="!editAble" type="primary" @click="editAble=true">编辑</el-button>
                  <el-button v-if="editAble" type="danger" @click="cancel">取消</el-button>
                  <el-button v-if="editAble" type="primary" @click="saveUser">保存</el-button>
                </span>
              </div>
            </div>
          </div>
        </el-main>
      </el-container>
    </div>
  </div>


</template>

<script>
import request from "@/utils/Request";
import {getImgBlob, defaultPass, loginReg, passReg, phoneNoReg} from "@/utils/Common";

export default {
  name: "ShopUserManager",
  data() {
    const validateIdCard = (rule, value, callback) => {
      if (!!!this.currentUser.idCardZmPath || !!!this.currentUser.idCardFmPath) {
        callback(new Error('请上传身份证'));
      } else {
        callback();
      }
    };
    const validatePass = (rule, value, callback) => {
      if (!!value && this.oriCurrentUser.password === value) {
        callback();
      } else if (!!!value) {
        callback(new Error('请输入密码'));
      } else if (!passReg.exp.test(value)) {
        callback(new Error(passReg.msg));
      } else if (value.length < 6 || value.length > 25) {
        callback(new Error('请输入6到25个字符'));
      } else {
        callback();
      }
    };
    const validateLoginId = (rule, value, callback) => {
      if (!!this.oriCurrentUser.loginId) {
        callback();
      }
      if (!value) {
        callback(new Error('请输入登录账号'));
      }
      request.get("/platUser/validateLoginId", {params: {loginId: value}}).then(({data}) => {
        if (data.success) {
          if (!loginReg.exp.test(value)) {
            callback(new Error(loginReg.msg));
          } else {
            callback();
          }
        } else {
          callback(new Error('账号已存在'));
        }
      }).catch(err => {
        callback(new Error('验证账号唯一性失败'));
      });
    };
    const validatePhoneNo = (rule, value, callback) => {
      if (!!!value) {
        callback(new Error('请输入电话'));
      } else if (!phoneNoReg.exp.test(value)) {
        callback(new Error(phoneNoReg.msg));
      } else {
        callback();
      }
    };
    return {
      clientHeight: 500,
      defaultPass: defaultPass,
      localStorage: localStorage,
      idCardZmList: [],
      idCardFmList: [],
      licensePathList: [],
      editAble: false,
      treeData: [],
      nodeData: {},
      parentNodeData: {},
      menuVisible: false,
      filterText: '',
      currentUser: {},
      oriCurrentUser: {},
      dialogImageUrl: '',
      dialogVisible: false,
      disabled: false,
      uploadUrl: window.config.BASE_API + '/upload/img',
      stopNode: {},
      rules: {
        idCardZmPath: [
          {
            required: true, validator: (rule, value, callback) => {
              validateIdCard.bind(this);
              return validateIdCard(rule, value, callback);
            }, trigger: 'change'
          }
        ],
        shopName: [
          {required: true, message: '请输入商户名称', trigger: 'blur'},
          {min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur'}
        ],
        userName: [
          {required: true, message: '请输入姓名', trigger: 'blur'},
          {min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur'}
        ],
        address: [
          {required: true, message: '请输入家庭住址', trigger: 'blur'},
          {min: 4, max: 30, message: '长度在 4 到 30 个字符', trigger: 'blur'}
        ],
        phoneNo: [
          {required: true, validator: validatePhoneNo, trigger: 'blur'}
        ],
        loginId: [
          {required: true, validator: validateLoginId, trigger: 'blur'}
        ],
        password: [
          {
            required: true, validator: (rule, value, callback) => {
              validatePass.bind(this);
              return validatePass(rule, value, callback);
            }, trigger: 'blur'
          }
        ]
      }
    }
  },
  mounted() {
    this.clientHeight = document.body.clientHeight - 180;
  },
  methods: {
    restPassword() {
      this.currentUser.password = this.defaultPass;
      request.post("/platUser/restPassword", {id: this.currentUser.id}).then(({data}) => {
        if (data.success) {
          this.$message({type: 'success', message: "恢复初始密码成功"});
        } else {
          this.$message({type: 'error', message: data.message});
        }
      }).catch(err => {
        this.$message({type: 'error', message: "重置密码失败"});
        console.log(err)
      })
    },
    shopNameInput(v) {
      if (this.nodeData.level === 3) {
        this.$set(this.nodeData.data, 'shopName', v);
      }
    },
    cancel() {
      this.setCurrentUser(this.oriCurrentUser);
      this.editAble = false;
    },
    async deleteUser() {
      const confirm = await this.$confirm('是否确认停用?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        return true;
      }).catch(() => {
        return false;
      });
      if (!confirm) {
        return;
      }
      request.post('/platUser/deleteShopUser', {id: this.nodeData.data.id}).then(({data}) => {
        if (data.success) {
          this.$message({type: 'success', message: "停用成功"});
          this.nodeData.parent.loaded = false;
          this.nodeData.parent.expand();
          this.stopNode.loaded = false;
          this.stopNode.expand();
        } else {
          throw new Error()
        }
      }).catch(err => {
        this.$message({type: 'error', message: "停用失败"});
        console.log(err)
      });
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    deleteNode() {
      this.hideContextmenu();
      if (this.nodeData.childNodes.length > 0) {
        this.$message({type: 'warning', message: "无法删除未清空的目录"});
      } else {
        request.post('/platUser/deleteDir', {id: this.nodeData.data.id}).then(({data}) => {
          if (data.success) {
            this.$message({type: 'success', message: "删除成功"});
            this.nodeData.parent.loaded = false;
            this.nodeData.parent.expand();
          } else {
            throw new Error()
          }
        }).catch(err => {
          this.$message({type: 'error', message: "删除失败"});
          console.log(err)
        });
      }
    },
    async saveUser() {
      const validate = await new Promise((resolve, reject) => {
        this.$refs.currentUser.validate((valid) => {
          if (valid) {
            resolve(true)
          } else {
            resolve(false);
          }
        });
      })
      if (!validate) {
        return;
      }
      const confirmMsg = this.oriCurrentUser.loginId !== this.currentUser.loginId ? '保存后登录账号将无法修改，' : '';
      const confirm = await this.$confirm(`${confirmMsg}是否确认保存?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        return true;
      }).catch(() => {
        return false;
      });
      if (!confirm) {
        return;
      }
      request.post('/platUser/saveUser', this.currentUser).then(({data}) => {
        if (data.success) {
          this.nodeData.parent.loaded = false;
          this.nodeData.parent.expand();
          this.$message({type: 'success', message: "保存商户成功"});
        } else {
          this.$message({type: 'warning', message: data.message});
        }
      }).catch(err => {
        this.$message({type: 'error', message: "保存商户失败"});
        console.log(err)
      }).finally(() => {
        this.editAble = false;
      });
    },
    clickNode(data, node) {
      if (data.type === 'user') {
        this.editAble = false;
        this.nodeData = node;
        this.setCurrentUser(data);
      }
    },
    setCurrentUser(data) {
      this.currentUser = JSON.parse(JSON.stringify(data));
      this.oriCurrentUser = JSON.parse(JSON.stringify(data));
      if (!!this.currentUser.idCardZmPath) {
        getImgBlob(this.currentUser.idCardZmPath, this.currentUser.idCardZmName).then(url => {
          this.idCardZmList = [{name: '', url}];
        });
      } else {
        this.idCardZmList = [];
      }
      if (!!this.currentUser.idCardFmPath) {
        getImgBlob(this.currentUser.idCardFmPath, this.currentUser.idCardFmName).then(url => {
          this.idCardFmList = [{name: '', url}];
        });
      } else {
        this.idCardFmList = [];
      }
      if (!!this.currentUser.licensePath) {
        getImgBlob(this.currentUser.licensePath, 'fileLicense').then(url => {
          this.licensePathList = [{name: '', url}];
        });
      } else {
        this.licensePathList = [];
      }
      this.shopNameInput(this.currentUser.shopName);
    },
    upload1Success({success, data}, file, fileList) {
      if (!success) {
        this.$message({type: 'error', message: "上传身份证失败"});
      } else {
        this.currentUser.idCardZmName = data.originalFilename;
        this.currentUser.idCardZmPath = data.filePath;
        this.idCardZmList = fileList;
      }
    },
    upload2Success({success, data}, file, fileList) {
      if (!success) {
        this.$message({type: 'error', message: "上传身份证失败"});
      } else {
        this.currentUser.idCardFmName = data.originalFilename;
        this.currentUser.idCardFmPath = data.filePath;
        this.idCardFmList = fileList;
      }
    },
    uploadLicensePathSuccess({success, data}, file, fileList) {
      if (!success) {
        this.$message({type: 'error', message: "上传营业执照失败"});
      } else {
        this.currentUser.licenseName = data.originalFilename;
        this.currentUser.licensePath = data.filePath;
        this.licensePathList = fileList;
      }
    },
    handleRemoveZm(file, fileList) {
      this.idCardZmList = [];
      this.currentUser.idCardZmPath = '';
      this.currentUser.idCardZmName = '';
    },
    handleRemoveFm(file, fileList) {
      this.idCardFmList = [];
      this.currentUser.idCardFmPath = '';
      this.currentUser.idCardFmName = '';
    },
    handleRemoveLicense(file, fileList) {
      this.licensePathList = [];
      this.currentUser.licensePath = '';
      this.currentUser.licenseName = '';
    },
    saveDir(nodeData, node) {
      if (!nodeData.label) {
        node.parent.loaded = false;
        node.parent.expand();
        return;
      }
      nodeData.edit = false;
      nodeData.parentId = node.parent.data.id;
      if (nodeData.type === "dir") {
        request.post('/platUser/saveDirName', nodeData).then(({data}) => {
          if (data.success) {
            this.$message({type: 'success', message: "保存文件夹名称成功"});
          } else {
            throw new Error()
          }
        }).catch(err => {
          this.$message({type: 'error', message: "保存文件夹名称失败"});
          console.log(err)
        });
      } else {
        request.post('/platUser/saveShopName', nodeData).then(({data}) => {
          if (data.success) {
            this.setCurrentUser({...data.data, type: 'user', password: this.defaultPass});
            this.$set(node, 'data', this.currentUser);
            node.parent.loaded = false;
            node.parent.expand();
            this.editAble = true;
          } else {
            throw new Error()
          }
        }).catch(err => {
          this.$message({type: 'error', message: "保存业务人员失败"});
          console.log(err)
        });
      }
    },
    addDir() {
      const childData = this.parentNodeData.childNodes.map(m => m.data);
      const ord = childData.length > 0 ? childData[childData.length - 2].ord + 1 : 1;
      const newChild = {id: `DIR${new Date().getTime()}`, label: '', edit: true, isLeaf: false, ord, type: 'dir'};
      if (!this.parentNodeData.data.children) {
        this.$set(this.parentNodeData.data, 'children', []);
      }
      let data1 = childData.slice(0, childData.length - 1);
      this.parentNodeData.data.children = ([...data1, newChild, childData[childData.length - 1]]);
      this.$nextTick(() => {
        this.$refs[`note${newChild.id}`].focus();
      })
    },
    addShopUser() {
      const childData = this.nodeData.childNodes.map(m => m.data);
      const ord = childData.length > 0 ? childData[childData.length - 1].ord + 1 : 1;
      const newChild = {id: `USER${new Date().getTime()}`, label: '', edit: true, isLeaf: true, ord, type: 'user'};
      if (!this.nodeData.data.children) {
        this.$set(this.nodeData.data, 'children', []);
      }
      this.nodeData.data.children = ([...childData, newChild]);
      this.$nextTick(() => {
        this.$refs[`note${newChild.id}`].focus();
      })
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    async getTreeDirData(parentDirId = '-1', isLeaf = false) {
      return await request.get('/platUser/getTreeDirData', {params: {parentDirId}}).then(({data}) => {
        if (data.success) {
          data.data.forEach(t => {
            t.isLeaf = isLeaf;
            t.edit = false;
            t.label = t.dirName;
            t.type = 'dir';
          });
          return data.data
        }
      }).catch(err => {
        this.$message({type: 'error', message: "查询商户目录失败"});
        console.log(err)
      })
    },
    async getTreeUserData(parentDirId, isLeaf = true, deleteFlag = null) {
      return await request.get('/platUser/getTreeUserData', {params: {parentDirId, deleteFlag}}).then(({data}) => {
        if (data.success) {
          data.data.forEach(t => {
            t.isLeaf = isLeaf;
            t.edit = false;
            t.label = t.shopName;
            t.type = 'user';
          });
          return data.data
        }
        return [];
      }).catch(err => {
        this.$message({type: 'error', message: "查询商户目录失败"});
        console.log(err)
      })
    },
    async loadNode(node, resolve) {
      if (node.data.id === '20000') {
        this.stopNode = node;
        return resolve(await this.getTreeUserData(node.data.id, true, "1"));
      }
      if (node.level === 0) {
        const dirData = await this.getTreeDirData('-10000');
        return resolve(dirData);
      }
      if (node.level === 1) {
        return resolve(await this.getTreeDirData(node.data.id));
      }
      if (node.level === 2) {
        return resolve(await this.getTreeUserData(node.data.id));
      }
      return resolve([]);
    },
    hideContextmenu() {
      this.menuVisible = false;
    },
    showEdit() {
      this.nodeData.data.edit = true;
    },
    rightClick(MouseEvent, object, Node, element) {
      if (Node.data.deleteFlag === '1' || Node.data.id === '20000' || Node.level === 1 || Node.level === 3) {
        return;
      }
      this.parentNodeData = Node.parent;
      this.nodeData = Node
      this.menuVisible = true;
      this.$nextTick(() => {
        let menu = document.querySelector("#menu");
        menu.style.cssText = "position: fixed; left: " + (MouseEvent.clientX - 10) + 'px' + "; top: " + (MouseEvent.clientY - 25) + 'px; z-index: 999; cursor:pointer;';
      })
    },
  },
  computed: {
    userInfo() {
      return JSON.parse(localStorage.getItem('userInfo'));
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    idCardZmList(val) {
      if (val.length === 1) {
        this.$refs.upload3.$children[1].$el.style.display = "none";
      } else {
        this.$refs.upload3.$children[1].$el.style.display = ''
      }
    },
    idCardFmList(val) {
      if (val.length === 1) {
        this.$refs.upload4.$children[1].$el.style.display = "none";
      } else {
        this.$refs.upload4.$children[1].$el.style.display = ''
      }
    },
    licensePathList(val) {
      if (val.length === 1) {
        this.$refs.upload5.$children[1].$el.style.display = "none";
      } else {
        this.$refs.upload5.$children[1].$el.style.display = ''
      }
    }
  }
}
</script>

<style scoped>

.text {
  font-size: 14px;
}

.item {
  margin-bottom: 18px;
}
.dialog-footer {
  align-items: center;
  width: 100%;
  display: flex;
  justify-content: center;
  background: #fff;

}
.box-card {
  width: 120px;
  background: #fff;
  border: 1px solid #EBEEF3;
  border-radius: 3px;
  box-shadow: 0px 0px 16px rgba(100, 108, 154, 0.2);
  padding: 10px 0;
}

.box-card > .ring_button {
  text-align: left;
  margin-left: 0;
  width: 120px;
  border: none;
  border-radius: 0;
}

.el-aside {
  background: none;
  color: #333;
  border-right: 1px solid #EBEEF3;
}

.el-main {
  color: #333;
}

body > .el-container {
  margin-bottom: 40px;
}
</style>